/* Example of embedding Python in another program */

#include "python2.6/Python.h"
#include "python2.6/structmember.h"
#include <iostream>
typedef struct {
    PyObject_HEAD
		float hodnota;
		PyObject *vlastnost;
    /* Type-specific fields go here. */
} oobj;
static PyMemberDef Noddy_members[] = {
    {"vlastnost", T_OBJECT_EX, offsetof(oobj, vlastnost), 0,
     "vlastnost toho objektu"},
    {NULL}  /* Sentinel */
};
static PyObject *husta_funkce(oobj* self){
	printf("jou, zavolals dost hustou funkci!");
}
static PyMethodDef Noddy_methods[] = {
    {"funkce", (PyCFunction)husta_funkce, METH_NOARGS,
     "Udela neco zvlastniho"
    },
    {NULL}  /* Sentinel */
};


static PyTypeObject noddy_NoddyType = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "noddy.Oobj",             /*tp_name*/
    sizeof(oobj), /*tp_basicsize*/
};

static PyObject *set_callback(PyObject *self, PyObject* args, PyObject *keywds);
static PyObject *return_something(PyObject *self, PyObject* args, PyObject *keywds){
	char* argument;
	PyObject *p;
	static char *kwlist[] = {"objekt", "argument", NULL};
	if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|s", kwlist, &p, &argument));
	PyObject_SetAttrString(p, "vlastnost", args);
			//p=Py_BuildValue("s", argument);
	return p;
}

static PyMethodDef embedder_methods[] = {
	{"setCallback", (PyCFunction)set_callback, METH_KEYWORDS, "Return the meaning of everything."},
	{"returnSomething", (PyCFunction)return_something, METH_KEYWORDS, "Return just something"},
	{NULL, NULL} /* sentinel */
};
static PyMethodDef lolz_methods[] = {
	{NULL, NULL}
};

void initembedder(){
	PyImport_AddModule("embedder");
	Py_InitModule("embedder", embedder_methods);
	PyImport_AddModule("lolz");
	PyObject *lolz = Py_InitModule("lolz", lolz_methods);

	noddy_NoddyType.tp_new = PyType_GenericNew;
	noddy_NoddyType.tp_methods= Noddy_methods;
	noddy_NoddyType.tp_members= Noddy_members;
	if (PyType_Ready(&noddy_NoddyType) < 0)
		fprintf(stderr, "FUCK THE SHIT DAMMIT!");
	Py_INCREF(&noddy_NoddyType);
	PyModule_AddObject(lolz, "Oobj", (PyObject *)&noddy_NoddyType);
}

PyObject *pCallbackFunction, *pModule;

main(int argc, char **argv)
{
	fprintf(stderr, "wtf");
	//Py_SetProgramName(argv[0]);
	Py_Initialize();
	initembedder();
	PySys_SetPath(".");
	//PySys_SetArgv(argc, argv);
	PyRun_SimpleString("print \"Hello, world!\"\n");
	fprintf(stderr, "wtfa");
	PyObject *pName, *pFunc;
	PyObject *pArgs, *pValue;
	int i;
	pName = PyString_FromString((const char*)"embed");
	/* Error checking of pName left out */
	fprintf(stderr, "wtfb");
	pModule=PyImport_ImportModule("embed");
	fprintf(stderr, "wtfc");
	Py_XDECREF(pName);
	if (pModule != NULL) {
		/*pFunc = PyObject_GetAttrString(pModule, "initialize");
		if (pFunc && PyCallable_Check(pFunc)) {
			pArgs = PyTuple_New(0);
			//PyTuple_SetItem(pArgs, 0, PyInt_FromLong(8));
			pValue = PyObject_CallObject(pFunc, pArgs);
			Py_DECREF(pArgs);
			if (pValue != NULL) {
				printf("Result of call: %ld\n", PyInt_AsLong(pValue));
				Py_DECREF(pValue);
			}
			else {
				Py_DECREF(pFunc);
				Py_DECREF(pModule);
				PyErr_Print();
				fprintf(stderr,"Call failed\n");
			}
		}
		else {
			if (PyErr_Occurred())
				PyErr_Print();
			fprintf(stderr, "Cannot find function \"initialize\"\n");
		}
		Py_XDECREF(pFunc);*/
		//Py_DECREF(pModule);
	}
	else {
		PyErr_Print();
		fprintf(stderr, "Failed to load \"embed.py\"\n");
	}
	fprintf(stderr, "wtf");
	if (pCallbackFunction && PyCallable_Check(pCallbackFunction)) {
		pArgs = PyTuple_New(0);
		pValue = PyObject_CallObject(pCallbackFunction, pArgs);
		Py_DECREF(pArgs);
		if (pValue != NULL) {
			printf("Result of callback: %ld\n", PyInt_AsLong(pValue));
			Py_DECREF(pValue);
		}
		else {
			Py_DECREF(pFunc);
			Py_DECREF(pModule);
			PyErr_Print();
			fprintf(stderr,"Callback failed\n");
		}
	}
	/* Note that you can call any public function of the Python
	   interpreter here, e.g. call_object(). */

	Py_Finalize();
	printf("Goodbye, cruel world\n");
}

/* A static module */
static PyObject *set_callback(PyObject *self, PyObject* args, PyObject *keywds){
	char *function, *event, *key;
	static char *kwlist[] = {"function", "event", "key", NULL};
	if ((pModule == NULL) || !PyArg_ParseTupleAndKeywords(args, keywds, "ss|s", kwlist, &function, &event, &key))
		return NULL;
	fprintf(stderr, "setting callback");
	pCallbackFunction = PyObject_GetAttrString(pModule, function);
	if (!pCallbackFunction || !PyCallable_Check(pCallbackFunction)){
		Py_XDECREF(pCallbackFunction);
		pCallbackFunction=NULL;
		printf("Failed to set callback\n");
		return Py_BuildValue("i", -1);
	}
	else {
		printf("Callback set\n");
		printf("Checking the function...");
		return PyObject_CallObject(pCallbackFunction, PyTuple_New(0));
	}
//	return Py_BuildValue("i",0);
}
